#ifndef MARINE_SM_H
#define MARINE_SM_H

#include <BWAPI.h>

class MarineSM;

class MarineBaseState
{
public:
	MarineBaseState(MarineSM* mk) {marineSM = mk;}
	virtual ~MarineBaseState() {}

	virtual void enter() = 0;
	virtual void onFrame() = 0;
	virtual void exit() = 0;

	BWAPI::Unit* getUnit();
	BWAPI::Unit* findNearestEnemy();
	BWAPI::Unit* findNearestMedic();
	MarineSM* findNearestMember();
	std::vector<MarineSM*>& getOtherMembers();

protected:
	MarineSM* marineSM;
	int exitTimer;
	bool beganTraining;
};

class MarineIdleState : public MarineBaseState
{
public:
	MarineIdleState(MarineSM* mk);
	virtual ~MarineIdleState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	int timeIdling;
};

class MarineWanderState : public MarineBaseState
{
public:
	MarineWanderState(MarineSM* mk);
	virtual ~MarineWanderState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class MarineAttackState : public MarineBaseState
{
public:
	MarineAttackState(MarineSM* mk);
	virtual ~MarineAttackState();

	MarineAttackState* reconstruct(BWAPI::Unit* target);

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	BWAPI::Unit* forceTarget;
};

class MarineFleeState : public MarineBaseState
{
public:
	MarineFleeState(MarineSM* mk);
	virtual ~MarineFleeState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class MarineScatterState : public MarineBaseState
{
public:
	MarineScatterState(MarineSM* mk);
	virtual ~MarineScatterState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class MarineHoldFlankState : public MarineBaseState
{
public:
	MarineHoldFlankState(MarineSM* mk);
	virtual ~MarineHoldFlankState();

	MarineHoldFlankState* reconstruct(BWAPI::Position pos);
	inline bool isInFlankPosition() {return inFlankPosition;}

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	BWAPI::Position flankPos;
	bool inFlankPosition;
};

class MarineSM
{
public:
	MarineSM(BWAPI::Unit* myUnit);
	virtual ~MarineSM();

	virtual void onFrame();
	
	virtual bool expired();

	void changeState(MarineBaseState* state);

	inline BWAPI::Unit* getUnit() const {return myUnit;}
	inline std::vector<MarineSM*>& getOtherMembers() {return otherMembers;}
	inline int getFrameCounter() {return frameCounter;}
	inline MarineWanderState* getWanderState() {return &wanderState;}
	inline MarineIdleState* getIdleState() {return &idleState;}
	inline MarineAttackState* getAttackState() {return &attackState;}
	inline MarineFleeState* getFleeState() {return &fleeState;}
	inline MarineScatterState* getScatterState() {return &scatterState;}

	void SetAttackTile(BWAPI::TilePosition attackTile);
	inline BWAPI::TilePosition GetAttackTile() {return masterAttackTile;}

protected:
	BWAPI::Unit* myUnit;
	BWAPI::Unit* mainTarget;
	BWAPI::TilePosition masterAttackTile;
	std::vector<MarineSM*> otherMembers;
	int frameCounter;

	MarineBaseState* currentState;
	MarineWanderState wanderState;
	MarineIdleState idleState;
	MarineAttackState attackState;
	MarineFleeState fleeState;
	MarineScatterState scatterState;
};

#endif

